package com.ctg.behavior.calc.impala.calculator;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.ctg.behavior.api.CtCalcStatus;
import com.ctg.behavior.calc.common.CtSQLParam;
import com.ctg.behavior.calc.impala.CtCalculator;
import com.ctg.behavior.calc.impala.builder.retentions.CtRetentionsCalcResultBuilder;
import com.ctg.behavior.calc.impala.builder.retentions.CtRetentionsReportBuilder;
import com.ctg.behavior.calc.impala.engine.ImpalaSQLEngine;
import com.ctg.behavior.calc.impala.report.retentions.CtRetentionsReport;
import com.ctg.behavior.calc.impala.transfer.retentions.CtRetentionsTransfer;
import com.ctg.behavior.calc.impala.utils.CtCalculatorUtils;
import com.ctg.behavior.client.impala.common.CtQueryResult;
import com.ctg.behavior.common.calc.CtCalcBody;
import com.ctg.behavior.common.calc.CtCalcResult;
import com.ctg.behavior.common.consts.CtCalcTaskConsts;
import com.ctg.behavior.common.retentions.CtRetentionsCalcBody;
import com.ctg.behavior.common.retentions.CtRetentionsCalcData;
import com.ctg.behavior.common.retentions.CtRetentionsCalcResult;
import com.ctg.behavior.utils.CtDateUtils;
import com.ctg.behavior.utils.CtStatusUtils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class CtRetentionsCalculator implements CtCalculator {

	@Autowired
	private CtRetentionsReportBuilder reportBuilder;
	@Autowired
	private CtRetentionsCalcResultBuilder calcResultBuilder;
	@Autowired
	private CtRetentionsTransfer retentionsTransfer;
	@Autowired
	private ImpalaSQLEngine sqlEngine;

	/****************************************************************
	 * @apiNote: 1.计算是按measure执行(一个measure对应一个独立执行体)
	 * @apiNote: 2.每个SQL的执行结果合并到CtRetentionsCalcResult中
	 */
	@Override
	public CtCalcResult doCalculator(CtCalcBody calcBody) {
		CtRetentionsCalcResult calcResult = new CtRetentionsCalcResult();
		if (!(calcBody instanceof CtRetentionsCalcBody)) {
			log.error("calcBody={}", calcBody.getClass());
			CtStatusUtils.fillStatus(calcResult, CtCalcStatus.BodyNoMatch);
			return calcResult;
		}
		CtRetentionsCalcData calcData = new CtRetentionsCalcData();
		calcResult.setValue(calcData);

		log.info("doBuilder-start: {}", CtDateUtils.getCurrentDateSSS());
		CtRetentionsCalcBody retentionsCalcBody = (CtRetentionsCalcBody) calcBody;
		// 1. 从CtRetentionsCalcBody组建CtRetentionsDayReport
		List<CtRetentionsReport> dayReports = reportBuilder.doBuilder(retentionsCalcBody);
		log.info("doBuilder-end: {}", CtDateUtils.getCurrentDateSSS());
		if (dayReports.isEmpty()) {
			CtStatusUtils.fillStatus(calcResult, CtCalcStatus.BodyIsEmpty);
			return calcResult;
		}
		// 2. 初始化ResultBuilder
		calcResultBuilder.resetResultBuilderTheadLocal();
		log.info("time - start: {}", CtDateUtils.getCurrentDateSSS());
		// 3. 分步计算，并合并每一步的计算结果
		for (CtRetentionsReport oneReport : dayReports) {
			log.info("one-time-start: {}", CtDateUtils.getCurrentDateSSS());
			// 3.1 转换成DayReport对应的SQL
			log.info("one-report={}", JSON.toJSONString(oneReport));
			String measureSql = retentionsTransfer.doTransfer(oneReport, CtSQLParam.createParam());
			String queryType = CtCalcTaskConsts.TASK_TYPE_RETENTION;
			CtQueryResult queryResult = sqlEngine.doQuery(queryType, measureSql);
			log.info("one-queryResult={}", JSON.toJSONString(queryResult.getRows()));
			CtCalculatorUtils.fillCalcResult(calcResult, queryResult);
			if (!calcResult.getSuccess()) {
				log.error(queryResult.getCode());
				break;
			}
			// 3.2 sqlEngine的结果转换并添加到CtRetentionsCalcResult
			calcData = calcResultBuilder.doBuilder(calcData, queryResult.getRows(), oneReport);
			log.info("one-result={}", JSON.toJSONString(calcData));
			log.info("one-time-end: {}", CtDateUtils.getCurrentDateSSS());
		}
		log.info("time - end: {}", CtDateUtils.getCurrentDateSSS());
		return calcResult;
	}

}
